package collector

import (
	"database/sql"
	"log/slog"

	"github.com/prometheus/client_golang/prometheus"
)

const (
	// Scrape query.
	globalQuery               = `select classid,name,stat_val from v$sysstat`
	memoryBufferPoolSizeQuery = `select sum(n_pages * page_size) from v$bufferpool`
	// Subsystem.
	globalStatus = "global_status"
)

/*
1	字典信息
2	SQL
3	事务
4 	检查点
5	RLOG
6	UNDO
7	IO
8	B树
9	网络
10	文件
11	内存
12	CPU
13	OS
14	缓冲区
15	限流控制
16	DMDPC
20	其它
*/

// 定义metricsDesc
var (
	globalCommandsDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, globalStatus, "commands_total"),
		"The DM commands count.",
		[]string{"command"}, nil,
	)
	globalTransactionDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, globalStatus, "transactions_total"),
		"The DM transaction count.",
		[]string{"type"}, nil,
	)
	globalIODesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, globalStatus, "io_total"),
		"The DM io info.",
		[]string{"type"}, nil,
	)
	globalNetworkDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, globalStatus, "network_total"),
		"The DM Networks info.",
		[]string{"type"}, nil,
	)
	globalMemoryDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, globalStatus, "memory_size_total"),
		"The DM memory info.",
		[]string{"type"}, nil,
	)
	globalCPUDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, globalStatus, "cpu_milliseconds_total"),
		"The DM CPU info.",
		[]string{"mode"}, nil,
	)
)

type GlobalStatus struct{}

// Name of the Scraper. Should be unique.
func (GlobalStatus) Name() string {
	return "globalStatus"
}
func (GlobalStatus) Scrape(db *sql.DB, ch chan<- prometheus.Metric, backupPath string, logger *slog.Logger) error {
	var (
		classid     string
		key         string
		val         sql.RawBytes
		buffer_size float64
	)

	//内存buffer使用量
	err := db.QueryRow(memoryBufferPoolSizeQuery).Scan(&buffer_size)
	if err != nil {
		return err
	}
	ch <- prometheus.MustNewConstMetric(
		globalMemoryDesc, prometheus.CounterValue, buffer_size,
		"buffer_pool_size_in_bytes",
	)

	globalStatusRows, err := db.Query(globalQuery)
	if err != nil {
		logger.Error("Failed to query global status", "error", err)
		return err
	}
	defer globalStatusRows.Close()

	for globalStatusRows.Next() {
		if err := globalStatusRows.Scan(&classid, &key, &val); err != nil {
			logger.Error("Failed to scan global status row", "error", err)
			return err
		}
		//func.go parseStatus
		if floatVal, ok := parseStatus(val); ok {
			key = vaildPrometheusName(key)

			switch classid {
			case "2": //SQL
				ch <- prometheus.MustNewConstMetric(
					globalCommandsDesc, prometheus.CounterValue, floatVal,
					key,
				)
			case "3": //transaction
				ch <- prometheus.MustNewConstMetric(
					globalTransactionDesc, prometheus.CounterValue, floatVal,
					key,
				)
			case "7": //IO
				ch <- prometheus.MustNewConstMetric(
					globalIODesc, prometheus.CounterValue, floatVal,
					key,
				)
			case "9": //网络
				ch <- prometheus.MustNewConstMetric(
					globalNetworkDesc, prometheus.CounterValue, floatVal,
					key,
				)
			case "11": //内存
				ch <- prometheus.MustNewConstMetric(
					globalMemoryDesc, prometheus.CounterValue, floatVal,
					key,
				)

			case "12": //CPU
				ch <- prometheus.MustNewConstMetric(
					globalCPUDesc, prometheus.CounterValue, floatVal,
					key,
				)
			}

		}
		// fmt.Println(key)
		// fmt.Println(string(val))
	}

	return nil
}

func init() {
	RegisterScraper("globalStatus", GlobalStatus{})
}

var _ Scraper = GlobalStatus{}
